#!/usr/bin/env python3.10
# -*- encoding: utf-8 -*-
'''
@File    :   posts.py
@Time    :   2023/05/05 09:57:49
@Author  :   windstarry 
@Version :   1.0
'''
# here put the import lib
from typing import List, Union

from fastapi import APIRouter, Depends, Path, Request
from pydantic import parse_obj_as
from tortoise.exceptions import OperationalError
from tortoise.transactions import atomic

from ..models import PostModel as Post,TagModel,PostTagsModel
from ..schemas import TagStatus,CreatePost,UpdatePost,PostOut,PostInfo,PostFilter,FailResp, PageSizePaginator, SingleResp,PageResp,SuccessResp

router = APIRouter(prefix='/article', tags=['文章管理'])


@router.post("", summary="文章添加")
async def create_post(req: Request, post: CreatePost):
    if await Post.filter(title=post.title).exists():
        return FailResp(code=10101, msg='当前标题已存在')
    tags = post.tags
    
    @atomic()
    async def add():
        post_obj = await Post.create(**post.dict())
        # 查询tag是否存在
        for info in tags:
            tag = await TagModel.filter(id=info.tid, status=1).first()
            if tag is not None:
                # post_tag关联表写入数据
                await PostTagsModel.create(post=post_obj, tag=tag, status=info.status)
    try:
        await add()
        return SuccessResp(data="创建成功!")
    except OperationalError:
        return FailResp(code=30301, msg="创建失败!")


@router.get('', summary='文章列表', response_model=PageResp[PostOut])
async def get_all_posts(pg: PageSizePaginator = Depends(PageSizePaginator()),
                          filters: PostFilter = Depends(PostFilter)):
    posts_list = Post.filter(is_published=True,status=1).all()
    page_data = await pg.output(posts_list, filters.dict(exclude_defaults=True))
    return PageResp[PostOut](data=page_data) 


@router.delete("/{pid}", summary="文章删除")
async def delete_post(req: Request, pid: int = Path(..., gt=0)):
    post_obj = await Post.get_or_none(pk=pid)
    if post_obj is None:
        return FailResp(code=30201, msg="文章不存在!")
    await Post.filter(pk=pid).update(status=9)
    return SuccessResp(data="删除成功!")


@router.get('/published/{pid}',summary="查询发布的文章")
async def get_post_published(req: Request,pid: int = Path(..., gt=0)):
    get_post = await Post.get_or_none(pk=pid, is_published=True, status=1)
    if get_post is None:
        return FailResp(code=30201, msg="文章不存在!")
    data = parse_obj_as(PostOut, get_post)
    return SingleResp[PostOut](data=data)


@router.put('/published/{pid}',summary="更新文章发布状态")
async def get_post_published(req: Request,pid: int = Path(..., gt=0)):
    get_post = await Post.get_or_none(pk=pid)
    if get_post is None:
        return FailResp(code=30201, msg="文章不存在!")
    if get_post.is_published:
        get_post.is_published = False
    else:
        get_post.is_published = True
    await get_post.save()
    msg = f"文章 [ID={get_post.pk}] 已"
    msg += "发布" if get_post.is_published else "取消发布"
    return SuccessResp(data=msg)
    


@router.get('/{pid}', summary="查询文章")
async def get_post(req: Request,pid: int = Path(..., gt=0)):
    post_obj = await Post.get_or_none(pk=pid,status=1)
    if post_obj is None:
        return FailResp(code=30201, msg="文章不存在!")
    # 查用户对应的角色
    result = await PostTagsModel.filter(post=post_obj, status__not=9).all()
    tag_list: List[TagStatus] = []
    for post_tag in result:
        tag_obj = await post_tag.tag.filter(status__not=9).all()
        tag_list.append(
            TagStatus(
                tid=tag_obj.id, name=tag_obj.name, status=post_tag.status
            )
        )
    post_obj.tags = tag_list
    data = parse_obj_as(PostInfo, post_obj)
    return SingleResp[PostInfo](data=data)


@router.put("/{pid}", summary="更新文章")
async def update_post(req: Request,
                      post: UpdatePost, 
                      pid: int = Path(..., gt=0)):
    post_obj = await Post.get_or_none(pk=pid)
    if post_obj is None:
        return FailResp(code=30201, msg="文章不存在!")
    if post_obj.title != post.title:
        check_post_name = await Post.get_or_none(title=post.title)
        if check_post_name:
            return FailResp(code=20502, msg=f"文章名{post.title}已存在")
    tags = post.tags
    
    # 使用事务，保证数据完整
    @atomic()
    async def update():
        # 更新分类
        update_data = post.dict(exclude_unset=True, exclude_none=True)
        await post_obj.update_from_dict(update_data)
        await post_obj.save()
        await PostTagsModel.filter(post=post_obj, status__not=9).update(status=9)
        # 查询tag是否存在
        for info in tags:
            tag = await TagModel.filter(id=info.tid, status=1).first()
            if tag is not None:
                if await PostTagsModel.filter(post=post_obj, tag=tag).first():
                    await PostTagsModel.filter(post=post_obj, tag=tag).update(status=1)
                else:
                    await PostTagsModel.create(post=post_obj, tag=tag, status=info.status)
    
    try:
        await update()
        return SuccessResp(data="更新成功!")
    except OperationalError:
        return FailResp(code=30301, msg="更新失败!")
    
    
